package cn.xshi.common.util;

import java.net.URI;
import java.util.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import cn.xshi.common.base.BaseRestUrl;
import cn.xshi.common.constant.CacheConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;
/**
 * @Desc restTemplate工具类
 * @Author 邓纯杰
 * @CreateTime 2012-12-12 12:12:12
 */
@Component
@Slf4j
public class RestTemplateUtil extends BaseRestUrl {

	@Resource
	RestTemplate restTemplate;

	public HttpHeaders setHeaders(HttpServletRequest request){
		HttpHeaders headers = new HttpHeaders();
		if(null == request){
			return headers;
		}
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String key = (String) headerNames.nextElement();
			String value = request.getHeader(key);
			headers.add(key, value);
		}

		//TODO 设置秘钥
		Map<String,String> map = new HashMap<>();
		map.put(CacheConstant.JEHC_CLOUD_KEY,getJehcCloudKey());
		map.put(CacheConstant.JEHC_CLOUD_SECURITY,getJehcCloudSecurity());
		Set<String> keys  = map.keySet();
		Iterator<String> iteratorK = keys.iterator();
		while (iteratorK.hasNext()) {
			String key = (String) iteratorK.next();
			if(null == key){
				continue;
			}
			headers.add(key,map.get(key));
		}
		return headers;
	}

	/**
	 * set Headers By mxy
	 * @param request
	 * @param key_
	 * @param val
	 * @return
	 */
	public HttpHeaders setHeaders(HttpServletRequest request,String key_,String val){
		HttpHeaders headers = new HttpHeaders();
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String key = (String) headerNames.nextElement();
			String value = request.getHeader(key);
			headers.add(key, value);
		}
		headers.add(key_,val);
		//TODO 设置秘钥
		Map<String,String> map = new HashMap<>();
		map.put(CacheConstant.JEHC_CLOUD_KEY,getJehcCloudKey());
		map.put(CacheConstant.JEHC_CLOUD_SECURITY,getJehcCloudSecurity());
		Set<String> keys  = map.keySet();
		Iterator<String> iteratorK = keys.iterator();
		while (iteratorK.hasNext()) {
			String key = (String) iteratorK.next();
			if(null == key){
				continue;
			}
			headers.add(key,map.get(key));
		}
		return headers;
	}

	/**
	 * set Headers By dengcj
	 * @param request
	 * @param kvMap
	 * @return
	 */
	public HttpHeaders setHeaders(HttpServletRequest request,Map<String,String> kvMap){
		HttpHeaders headers = new HttpHeaders();
		Enumeration<String> headerNames = request.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String key = (String) headerNames.nextElement();
			String value = request.getHeader(key);
			headers.add(key, value);
		}
		Set<String> keys  = kvMap.keySet();
		Iterator<String> iteratorK = keys.iterator();
		while (iteratorK.hasNext()) {
			String key = (String) iteratorK.next();
			if(null == key){
				continue;
			}
			headers.add(key,kvMap.get(key));
		}

		//TODO 设置秘钥
		Map<String,String> map = new HashMap<>();
		map.put(CacheConstant.JEHC_CLOUD_KEY,getJehcCloudKey());
		map.put(CacheConstant.JEHC_CLOUD_SECURITY,getJehcCloudSecurity());
		Set<String> keys1  = map.keySet();
		Iterator<String> iteratorK1 = keys1.iterator();
		while (iteratorK1.hasNext()) {
			String key = (String) iteratorK1.next();
			if(null == key){
				continue;
			}
			headers.add(key,map.get(key));
		}
		return headers;
	}

	/**
	 * Get（Does not contain input parameters）
	 * @param url
	 * @param request
	 * @return
	 */
	public String get(String url,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
		ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
		if(null != response){
			return response.getBody();
		}
		return null;
	}

	/**
	 * Get（Does not contain input parameters）
	 * @param url
	 * @param request
	 * @return
	 */
	public <T> T get(String url,Class<T> out,HttpServletRequest request) {
		HttpHeaders httpHeaders = null;
		if(null != request){
			httpHeaders = setHeaders(request);
		}
		HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
		if(null != response){
			return response.getBody();
		}
		return null;
	}

	/**
	 * Get（Does not contain input parameters）
	 * @param url
	 * @param request
	 * @return
	 */
	public <T> T get(String url,Class<T> out,HttpServletRequest request,HttpHeaders headers) {
		HttpHeaders httpHeaders = null;
		if(null != request){
			httpHeaders = setHeaders(request);
			httpHeaders.addAll(headers);
		}
		HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
		if(null != response){
			return response.getBody();
		}
		return null;
	}
	/**
	 * Get（Does not contain input parameters）
	 * @param url
	 * @param headers
	 * @return
	 */
	public <T> T getUnRequest(String url,Class<T> out,HttpHeaders headers) {
		HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, headers);
		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
		if(null != response){
			return response.getBody();
		}
		return null;
	}

//
//	/**
//	 * Get（Contains input parameters）
//	 * @param url
//	 * @param request
//	 * @return
//	 */
//	public <T> T get(String url,Class<T> out,Object input,HttpServletRequest request) {
//		HttpHeaders httpHeaders = setHeaders(request);
//		httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
//		httpHeaders.add("Accept", "*/*");
//		List<MediaType> acceptableMediaTypes = new ArrayList<>();
//		acceptableMediaTypes.add(MediaType.ALL);
//		httpHeaders.setAccept(acceptableMediaTypes);
//		HttpEntity<Object> httpEntity = new HttpEntity<Object>(input, httpHeaders);
//		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, out);
//		if(null != response){
//			return response.getBody();
//		}
//		return null;
//	}

	/**
	 * post Request, including path, return type, Header, Parameter
	 * @param url
	 * @param out
	 * @param header
	 * @param input
	 * @param jsonBody
	 * @return
	 */
	public <T> T post(String url, Class<T> out, Map<String, Object> header,Object input, String jsonBody,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		if (header != null) {
			Set<String> keys = header.keySet();
			for (Iterator<String> i = keys.iterator(); i.hasNext();) {
				String key = (String) i.next();
				httpHeaders.add(key, header.get(key).toString());
			}
		}
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		httpHeaders.add("Accept", "*/*");
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
		acceptableMediaTypes.add(MediaType.ALL);
		httpHeaders.setAccept(acceptableMediaTypes);
		HttpEntity<Object> formEntity = new HttpEntity<Object>(jsonBody, httpHeaders);
		return restTemplate.postForObject(url, formEntity, out, input);
	}

	/**
	 * post（Contains input parameters）
	 * @param url
	 * @param out
	 * @param input
	 * @return
	 */
	public <T> T post(String url, Class<T> out,Object input) {
		HttpHeaders httpHeaders = setHeaders(null);
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		httpHeaders.add("Accept", "*/*");
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
		acceptableMediaTypes.add(MediaType.ALL);
		httpHeaders.setAccept(acceptableMediaTypes);
		HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
		return restTemplate.postForObject(url, formEntity, out);
	}

	/**
	 * post（Contains input parameters）
	 * @param url
	 * @param out
	 * @param input
	 * @param request
	 * @return
	 */
	public <T> T post(String url, Class<T> out,Object input,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		httpHeaders.add("Accept", "*/*");
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
		acceptableMediaTypes.add(MediaType.ALL);
		httpHeaders.setAccept(acceptableMediaTypes);
		HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
		return restTemplate.postForObject(url, formEntity, out);
	}

	/**
	 * post（Contains input parameters）
	 * @param url
	 * @param out
	 * @param input
	 * @return
	 */
	public <T> T post(String url, Class<T> out,Object input,HttpHeaders httpHeaders) {
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		httpHeaders.add("Accept", "*/*");
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
		acceptableMediaTypes.add(MediaType.ALL);
		httpHeaders.setAccept(acceptableMediaTypes);
		HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
		return restTemplate.postForObject(url, formEntity, out);
	}

	/**
	 * Post（Does not contain any input parameters）
	 * @param url
	 * @param out
	 * @param request
	 * @return
	 */
	public <T> T post(String url, Class<T> out,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		httpHeaders.add("Accept", "*/*");
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
		acceptableMediaTypes.add(MediaType.ALL);
		httpHeaders.setAccept(acceptableMediaTypes);
		HttpEntity<T> formEntity = new HttpEntity<T>(httpHeaders);
		return restTemplate.postForObject(url, formEntity, out);
	}

	/**
	 * post uriVariables
	 * @param url
	 * @param out
	 * @param input
	 * @param uriVariables
	 * @param request
	 * @param <T>
	 * @return
	 */
	public <T> T post(String url, Class<T> out, Object input,Map<String, Object> uriVariables,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
//		httpHeaders.add("Accept", "*/*");
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
//		acceptableMediaTypes.add(MediaType.ALL);
//		httpHeaders.setAccept(acceptableMediaTypes);
		HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
		return restTemplate.postForObject(url, formEntity, out, uriVariables);
	}

	/**
	 * post upload file
	 * @param url
	 * @param out
	 * @param input
	 * @param request
	 * @param <T>
	 * @return
	 */
	public <T> T post(String url, Class<T> out,MultiValueMap<String, Object> input ,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		httpHeaders.add("Accept", "*/*");
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
		httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
		acceptableMediaTypes.add(MediaType.ALL);
		httpHeaders.setAccept(acceptableMediaTypes);

		ClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory();
		restTemplate.setRequestFactory(clientFactory);
		URI uri = UriComponentsBuilder.fromUriString(url).build().encode().toUri();
		HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(input, httpHeaders);
		ResponseEntity<T> responseEntity = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, out);
		return responseEntity.getBody();
	}

	/**
	 * Put
	 * @param url
	 * @param out
	 * @param input
	 * @param request
	 * @return
	 */
	public <T> T put(String url, Class<T> out,Object input,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		httpHeaders.add("Accept", "*/*");
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		List<MediaType> acceptableMediaTypes = new ArrayList<>();
		acceptableMediaTypes.add(MediaType.ALL);
		httpHeaders.setAccept(acceptableMediaTypes);
		HttpEntity<Object> formEntity = new HttpEntity<Object>(input,httpHeaders);
		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.PUT, formEntity, out);
		if(null != response){
			return response.getBody();
		}
		return null;
	}


	/**
	 * delete（Contains MultiValueMap<String, Object> parameters）
	 * @param url
	 * @param input （MultiValueMap<String, Object> Type）
	 * @param request
	 * @return
	 */
	public <T> T delete(String url,Class<T> out,Map<String, ?> input,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		HttpEntity<Map<String, ?>> httpEntity = new HttpEntity<Map<String, ?>>(input, httpHeaders);
		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity,out);
		if(null != response){
			return response.getBody();
		}
		return null;
	}

	/**
	 * delete（Contains the Object parameter）
	 * @param url
	 * @param input （Object Type）
	 * @param request
	 * @return
	 */
	public <T> T delete(String url,Class<T> out,Object input,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		httpHeaders.setContentType(MediaType.APPLICATION_JSON);
		HttpEntity<Object> httpEntity = new HttpEntity<Object>(input, httpHeaders);
		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, out);
		if(null != response){
			return response.getBody();
		}
		return null;
	}


	/**
	 * delete（Does not contain input parameters）
	 * @param url
	 * @param request
	 * @return
	 */
	public <T>T delete(String url,Class<T> out,HttpServletRequest request) {
		HttpHeaders httpHeaders = setHeaders(request);
		HttpEntity<?> httpEntity = new HttpEntity<>(null, httpHeaders);
		ResponseEntity<T> response = restTemplate.exchange(url, HttpMethod.DELETE, httpEntity, out);
		if(null != response){
			return response.getBody();
		}
		return null;
	}

	/**
	 *
	 * @param url
	 * @param request
	 * @return
	 */
	public byte[] exportForGet(String url,HttpServletRequest request) {
		try {
			ResponseEntity<byte[]> entity = restTemplate.getForEntity(url, byte[].class);
			byte[] bytes = entity.getBody();
			return bytes;
		} catch (Exception e) {
			log.error("下载文件接口调用失败",e);
		}
		return null;
	}

	/**
	 *
	 * @param url
	 * @param request
	 * @param headers
	 * @return
	 */
	public byte[] exportForGet(String url,HttpServletRequest request,HttpHeaders headers) {
		try {
			HttpHeaders httpHeaders = null;
			if(null != request){
				httpHeaders = setHeaders(request);
				httpHeaders.addAll(headers);
			}
			HttpEntity<Object> httpEntity = new HttpEntity<Object>(null, httpHeaders);
			ResponseEntity<byte[]> entity = restTemplate.getForEntity(url, byte[].class,httpEntity);
			byte[] bytes = entity.getBody();
			return bytes;
		} catch (Exception e) {
			log.error("下载文件接口调用失败",e);
		}
		return null;
	}
}
